#!/bin/bash

NOFEXPEVENTS=-1
MAXINDEX="--max-index -1"
TRANSPORT="--transport zeromq"
VERBOSE="--severity INFO"
FAIRTASKNAME="--task-name PixelAltFindHits"
INPUTTYPE="dat"
OUTPUTTYPE="root"
AGGREGATE="--aggregate 1"

WORKDIR="@PIXEL_FILE_LOCATION@"

NOFPROCESSORS=2
FORCEKILL=false
COMMAND="interactive"
MAXRUNNINGTIME=100
DATESTRING=`date +%Y%m%d_%H%M%S`

while [[ $# > 1 ]]
do
key="$1"

case $key in
    -f|--task-name)
        FAIRTASKNAME="--task-name $2"
        shift
        ;;
    -m|--max-index)
        NOFEXPEVENTS=$2
        MAXINDEX="--max-index $2"
        shift
        ;;
    -t|--transport)
        TRANSPORT="--transport $2"
        shift
        ;;
    -i|--input-type)
        INPUTTYPE="$2"
        shift
        ;;
    -o|--output-type)
        OUTPUTTYPE="$2"
        shift
        ;;
    -a|--aggregate)
        AGGREGATE="--aggregate $2"
        shift
        ;;
    -p|--nof-processors)
       NOFPROCESSORS="$2"
        shift
        ;;
    -c|--command)
        COMMAND="$2"
        shift
        ;;
    -r|--max-running-time)
        MAXRUNNINGTIME="$2"
        shift
        ;;
    -w|--work-dir)
        WORKDIR="$2"
        shift
        ;;
    -k|--force-kill)
        FORCEKILL="$2"
        shift
        ;;
    -v|--verbose)
        VERBOSE="--severity $2"
        shift
        ;;
esac
shift 
done

CONTROL=""
if [ "$COMMAND" == "static" ]; then
    CONTROL="--control static --log-color false"
fi

########################### Define some variables
# ASCII and ROOT parameter files for the processor device
ROOTPARAM="$WORKDIR/examples/MQ/pixelDetector/macros/pixel_TGeant3.params.root"
ASCIIPARAM="$WORKDIR/examples/MQ/pixelDetector/param/pixel_digi.par"

if [ "$FAIRTASKNAME" == "--task-name PixelAltFindHits" ] ; then
    # input file and branch for the sampler device
    if [ "$INPUTTYPE" == "dat" ] ; then
        INPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/digisBin.dat"
    elif [ "$INPUTTYPE" == "root" ] ; then
        INPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/pixel_TGeant3.digi.root"
        INPUTBRANCH="PixelDigis"
    fi
    
    # output file for sink
    if [ "$OUTPUTTYPE" == "dat" ] ; then
        OUTPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQa.pixel_TGeant3.bin.hits.dat"
    elif [ "$OUTPUTTYPE" == "root" ] ; then
        OUTPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQa.pixel_TGeant3.bin.hits.root"
        OUTPUTCLASS="--class-name TClonesArray(PixelHit)"
        OUTPUTBRANCH="--branch-name PixelHits"
    fi
else
    echo "TASK $FAIRTASKNAME UNKNOWN!!!"
    exit
fi
###########################



########################### Start the chain of the devices


########################## start Parameter server
SERVER="@FAIRROOT_BIN_LOCATION@/"
SERVER+="parmq-server $TRANSPORT $CONTROL"
SERVER+=" --id pixAlt-parmq-server  --channel-config name=param,type=rep,method=bind,rateLogging=0,address=tcp://*:5305"
SERVER+=" --channel-name param --first-input-name $ROOTPARAM --second-input-name $ASCIIPARAM --second-input-type ASCII"
########################## start SAMPLER
if [ "$INPUTTYPE" == "dat" ] ; then
    SAMPLER="@PIXALT_BIN_LOCATION@/"
    SAMPLER+="pixalt-samplerBin $TRANSPORT"
    SAMPLER+=" $AGGREGATE"
elif [ "$INPUTTYPE" == "root" ] ; then
    SAMPLER="@PIXEL_BIN_LOCATION@/"
    SAMPLER+="pixel-samplerBin $TRANSPORT"
    SAMPLER+=" --branch-name EventHeader. --branch-name $INPUTBRANCH"
fi
SAMPLER+=" --id pixAlt-sampler1 --channel-config name=data-out,type=push,method=bind,rateLogging=1,address=tcp://*:5306"
if [ "$COMMAND" == "static" ]; then
    SAMPLER+=" --ack-channel ack --channel-config name=ack,type=pull,method=bind,rateLogging=1,address=tcp://*:5308"
fi
SAMPLER+=" --file-name $INPUTFILE $MAXINDEX --severity info $CONTROL"
########################## start PROCESSORs
PROCESSOR="@PIXALT_BIN_LOCATION@/"
PROCESSOR+="pixalt-processorBin $TRANSPORT"
PROCESSOR+=" $VERBOSE"
PROCESSOR+=" $FAIRTASKNAME $CONTROL"
PROCESSOR+=" --channel-config name=param,type=req,method=connect,rateLogging=0,address=tcp://localhost:5305"
PROCESSOR+=" --channel-config name=data-in,type=pull,method=connect,rateLogging=1,address=tcp://localhost:5306"
PROCESSOR+=" --channel-config name=data-out,type=push,method=connect,rateLogging=1,address=tcp://localhost:5307"

for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
do
    APROCESSOR[i]="$PROCESSOR --id pixAlt-processor$((i+1))"
done
########################## start FILESINK
if [ "$OUTPUTTYPE" == "dat" ] ; then
    FILESINK="@PIXALT_BIN_LOCATION@/"
    FILESINK+="pixalt-sinkBin $TRANSPORT"
elif [ "$OUTPUTTYPE" == "root" ] ; then
    FILESINK="@PIXEL_BIN_LOCATION@/"
    FILESINK+="pixel-sinkBin $TRANSPORT"
    FILESINK+=" --class-name FairEventHeader --branch-name EventHeader. $OUTPUTCLASS $OUTPUTBRANCH"
fi
FILESINK+=" --id pixAlt-sink1 --channel-config name=data-in,type=pull,method=bind,rateLogging=1,address=tcp://*:5307"
if [ "$COMMAND" == "static" ]; then
    FILESINK+=" --ack-channel ack --channel-config name=ack,type=push,method=connect,rateLogging=0,address=tcp://localhost:5308"
fi
FILESINK+=" --file-name $OUTPUTFILE $CONTROL"

########################## run all
if [ "$COMMAND" == "print" ]; then
    echo $SERVER
    echo $SAMPLER

    echo "THERE ARE $NOFPROCESSORS PROCESSORS."
    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        echo ${APROCESSOR[i]}
    done

    echo $FILESINK
fi

if [ "$COMMAND" == "interactive" ]; then
    xterm -geometry 80x25+0+350 -hold -e $SERVER &
    xterm -geometry 80x25+0+0 -hold -e $SAMPLER &
    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        xterm -geometry 80x50+500+0 -hold -e ${APROCESSOR[i]} &
    done
    xterm +aw -geometry 100x25+0+700 -hold -e $FILESINK &
fi

if [ "$COMMAND" == "static" ]; then

    CHECK_BEFORE="$(ps -fea | grep pixAlt | grep -v grep)"
    if [ -n "$CHECK_BEFORE" ];
    then
        echo "some example/MQ/pixel programs are still running:"
        echo $CHECK_BEFORE
        echo "quit them before proceeding."
        if [ "$FORCEKILL" == "true" ];
        then
            echo "trying to kill..."
            ps -fea | grep pixAlt | grep -v grep | awk '{print $2}' | xargs kill -9
        else
            exit
        fi
    fi

    $SERVER &> server_$DATESTRING.out.log &
    SERVER_PID=$!

    $SAMPLER &> sampler_$DATESTRING.out.log &
    SAMPLER_PID=$!

    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        ${APROCESSOR[i]} &> processor${i}_$DATESTRING.out.log &
        APROCESSOR_PID[i]=$!
    done

    $FILESINK &> fileSink_$DATESTRING.out.log &
    FILESINK_PID=$!

    RUN_STRING="Running"

    for (( iproc=0 ; iproc<$NOFPROCESSORS+3 ; iproc++ ))
    do
        printf "_______________"
    done
    printf "_\n|    server    |"
    printf "    sampler   |"
    for (( iproc=0 ; iproc<$NOFPROCESSORS ; iproc++ ))
    do
        printf "   processor  |"
    done
    printf "   file sink  |\n| pid = %6d | pid = %6d |" $SERVER_PID $SAMPLER_PID
    for (( iproc=0 ; iproc<$NOFPROCESSORS ; iproc++ ))
    do
        printf " pid = %6d |" ${APROCESSOR_PID[iproc]}
    done
    printf " pid = %6d |\n" $FILESINK_PID
    for (( iproc=0 ; iproc<$NOFPROCESSORS+3 ; iproc++ ))
    do
        printf "|   CPU    mem ";
    done
    printf "|\n"

    SAMPLERRUNNING=0
    for ((isec = 0 ; isec < MAXRUNNINGTIME ; isec++ ));
    do
        CHECK_SAMPLER="$(kill -0 $SAMPLER_PID &> /dev/null && echo $RUN_STRING)";
        if [ "$CHECK_SAMPLER" != "$RUN_STRING" ];
        then
            break;
        fi

        SERVER_INFO="$(ps -o %cpu -o rss $SERVER_PID | tail -1)"
        SAMPLER_INFO="$(ps -o %cpu -o rss $SAMPLER_PID | tail -1)"
        printf   "| %5s %6s | %5s %6s |" $SERVER_INFO $SAMPLER_INFO
        for (( iproc=0 ; iproc<$NOFPROCESSORS ; iproc++ ))
        do
            APROCESSOR_INFO="$(ps -o %cpu -o rss ${APROCESSOR_PID[iproc]} | tail -1)"
            printf " %5s %6s |" $APROCESSOR_INFO;
        done
        FILESINK_INFO="$(ps -o %cpu -o rss $FILESINK_PID | tail -1)"
        printf   " %5s %6s |\r" $FILESINK_INFO
        sleep 1
    done
    for (( iproc=0 ; iproc<$NOFPROCESSORS+3 ; iproc++ ))
    do
        printf "_______________"
    done
    printf "_\n"

    echo "Jobs finished in $isec seconds."

    sleep 2;

    kill $SERVER_PID
    CHECK_SAMPLER="$(kill -0 $SAMPLER_PID &> /dev/null && echo $RUN_STRING)";
    if [ "$CHECK_SAMPLER" == "$RUN_STRING" ];
    then
        kill $SAMPLER_PID;
    fi
    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        CHECK_APROCESSOR="$(kill -0 ${APROCESSOR_PID[isimul]} &> /dev/null && echo $RUN_STRING)";
        if [ "$CHECK_APROCESSOR" == "$RUN_STRING" ];
        then
            kill ${APROCESSOR_PID[i]};
        fi
    done
    kill $FILESINK_PID

    wait $FILESINK_PID

    OUTPUT_EVENTS="$(echo "cout<<cbmsim->GetEntries()<<endl;" | root -l -b $OUTPUTFILE | tail -1)"
    echo "There are $OUTPUT_EVENTS events in the output file ($NOFEXPEVENTS events expected)."

    if [ "$OUTPUT_EVENTS" -eq "$NOFEXPEVENTS" ];
    then
        echo "Shell script finished successfully.";
    fi
fi
